package com.hly.tool.list;

import com.matrixone.apps.domain.DomainConstants;
import com.matrixone.apps.domain.util.MapList;
import com.matrixone.apps.framework.ui.UIUtil;
import matrix.util.StringList;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * @Auther: Jack.Hao
 * @Date: 2021/5/5 10:41
 * @Description:
 */
public class ListUtil
{


    /**
     * 把集合分割成指定长度的子集合
     *
     * @param list 源数据集合
     * @param len  长度
     * @param <T>  数据类型
     * @return
     */
    public static <T> List<List<T>> splitList(List<Map> list, int len)
    {

        if (list == null || list.isEmpty() || len < 1)
        {
            return Collections.emptyList();
        }

        List<List<T>> result = new ArrayList<List<T>>();

        int size = list.size();
        int count = (size + len - 1) / len;

        for (int i = 0; i < count; i++)
        {
            List<T> subList = (List<T>) list.subList(i * len, ((i + 1) * len > size ? size : len * (i + 1)));
            result.add(subList);
        }

        return result;
    }


    /**
     * List 集合根据 下角标集合分割成 多个子集合
     *
     * @param dataList
     * @param indexList
     * @return
     */
    public static List<List> splitListByIndexList(List dataList, List<Integer> indexList)
    {
        List returnList = new ArrayList<>();
        if (dataList == null || dataList.size() == 0)
        {
            return returnList;
        }
        if (indexList == null || indexList.size() == 0)
        {
            returnList.add(dataList);
            return returnList;
        }

        int index0 = indexList.get(0);
        if (index0 != 0)
        {
            indexList.add(0, 0);
        }

        int dataListSize = dataList.size();
        int indexSize = indexList.size();
        for (int i = 0; i < indexSize; i++)
        {
            int index_i = indexList.get(i);

            if (index_i == dataListSize - 1)
            {
                //当角标集合中最后一个数据 是 被分割几个的最后一个数据的下角标
                Map map_last = (Map) dataList.get(index_i);
                List lastSub = new ArrayList<>();
                lastSub.add(map_last);
                returnList.add(lastSub);
            } else if (index_i < dataListSize - 1)//当角标集合中最后一个数据 不是 被分割集合的最后一个数据的下角标
            {
                if (i < indexSize - 1)
                {//处理角标集合中最后一个之前的数据
                    int index_next = indexList.get(i + 1);
                    returnList.add(dataList.subList(index_i, index_next));
                } else
                {//处理角标集合中最后一个数据
                    returnList.add(dataList.subList(index_i, dataListSize));
                }
            }
        }

        return returnList;
    }


    /**
     * 获取层次 集合中数据的下角标集合
     *
     * @param mapList
     * @return
     */
    public static List<Integer> getIndexListByMapValue(List<Map<String, String>> mapList, String level, String levelColumn, String nextLevel, int parentIndex)
    {

        List<Integer> parentLevel = getIndexListByMapValue(mapList, levelColumn, level);
//        System.out.println("parentLevel = " + parentLevel);

        int p_s_index = parentLevel.indexOf(parentIndex);
//        System.out.println("p_s_index = " + p_s_index);

        int parentEnd = 0;
        if (parentLevel.size() > 1)
        {
            int p_e_index = 0;
            if (p_s_index < parentLevel.size() - 1)
            {
                p_e_index = p_s_index + 1;
                parentEnd = parentLevel.get(p_e_index);
            } else
            {
                parentEnd = mapList.size();
            }
        } else
        {
            parentEnd = mapList.size();
        }


        List<Integer> indexList = new ArrayList<Integer>();
        for (int i = parentIndex; i < parentEnd; i++)
        {
            Map<String, String> map_i = mapList.get(i);
            String str_i = map_i.get(levelColumn);
            if (str_i != null && str_i.length() > 0 && str_i.trim().equals(nextLevel))
            {
                indexList.add(i);
            }
        }
        return indexList;
    }


    /**
     * 获取层次  集合中数据的下角标集合
     *
     * @param mapList
     * @return
     */
    public static List<Integer> getIndexListByMapValue(List<Map<String, String>> mapList, String levelColumn, String nextLevel, int parentIndex)
    {
        List<Integer> indexList = new ArrayList<Integer>();
        for (int i = parentIndex; i < mapList.size(); i++)
        {
            Map<String, String> map_i = mapList.get(i);
            String str_i = map_i.get(levelColumn);
            if (str_i != null && str_i.length() > 0 && str_i.trim().equals(nextLevel))
            {
                indexList.add(i);
            }
        }
        return indexList;
    }


    /**
     * 获取层次 集合中数据的下角标集合
     *
     * @param mapList
     * @return
     */
    public static List<Integer> getIndexListByMapValue(List<Map<String, String>> mapList, String levelColumn, String nextLevel)
    {
        List<Integer> indexList = new ArrayList<Integer>();
        for (int i = 0; i < mapList.size(); i++)
        {
            Map<String, String> map_i = mapList.get(i);
            String str_i = map_i.get(levelColumn);
            if (str_i != null && str_i.length() > 0 && str_i.trim().equals(nextLevel))
            {
                indexList.add(i);
            }
        }
        return indexList;
    }


    /**
     * 获取层次 集合中数据的下角标集合
     *
     * @param mapList
     * @return
     */
    public static List<Integer> getIndexListByMapValue(List<Map<String, String>> mapList, String levelColumn, int columnLength)
    {
        List<Integer> indexList = new ArrayList<Integer>();
        for (int i = 0; i < mapList.size(); i++)
        {
            Map<String, String> map_i = mapList.get(i);
            String str_i = map_i.get(levelColumn);
            if (str_i != null && str_i.length() > 0 && str_i.length() == columnLength)
            {
                indexList.add(i);
            }
        }
        return indexList;
    }


    /**
     * 从MapList 中获取type 集合
     *
     * @param mapList
     * @return
     */
    public static List<String> getIdList(MapList mapList)
    {
        List<String> idList = (List<String>) mapList.stream().map(m -> ((String) ((Map) m).get(DomainConstants.SELECT_ID))).collect(Collectors.toList());
        return idList;
    }


    /**
     * 从MapList 中获取type 集合
     *
     * @param mapList
     * @return
     */
    public static List<String> getTypeList(MapList mapList)
    {
        List<String> typeList = (List<String>) mapList.stream().map(m -> ((String) ((Map) m).get(DomainConstants.SELECT_TYPE))).collect(Collectors.toList());
        return typeList;
    }


    /**
     * 从MapList 中获取type 集合
     *
     * @param mapList
     * @return
     */
    public static List<String> getNameList(MapList mapList)
    {
        List<String> nameList = (List<String>) mapList.stream().map(m -> ((String) ((Map) m).get(DomainConstants.SELECT_NAME))).collect(Collectors.toList());
        return nameList;
    }


    /**
     * 从MapList 中获取指定属性的集合
     * * @param mapList
     *
     * @return
     */
    public static List<String> getAttrList(MapList mapList, String attr)
    {
        List<String> attrList = (List<String>) mapList.stream().map(m -> ((String) ((Map) m).get(attr))).collect(Collectors.toList());
        return attrList;
    }

    /**
     * 从MapList 值 转换成 map
     * * @param mapList
     *
     * @return
     */
    public static Map<String, String> getValMap(MapList mapList,String keyName,String valName)
    {
        Map<String, String> resultMap = (Map<String, String>) mapList.stream().collect(Collectors.toMap(m -> ((Map)m).get(keyName).toString(), m -> ((Map)m).get(valName)));
        return resultMap;
    }





    /**
     * 获取MapList 中的数据
     * 通过一个属性的属性值
     *
     * @param dataList
     * @param attr
     * @param attrValue
     * @return
     */
    public static MapList getMapListByAttrValue(MapList dataList, String attr, String attrValue)
    {
        MapList result = new MapList();
        if (attrValue == null)
        {
            return result;
        }
        String tmpAttr = "attribute[" + attr + "]";
        for (int i = 0; i < dataList.size(); i++)
        {
            Map map_i = (Map) dataList.get(i);

            if (map_i.containsKey(attr))
            {
                String attrVal = (String) map_i.get(attr);
                if (attrVal != null && attrVal.equals(attrValue))
                {
                    result.add(map_i);
                }
            } else if (map_i.containsKey(tmpAttr))
            {
                String attrVal = (String) map_i.get(tmpAttr);
                if (attrVal != null && attrVal.equals(attrValue))
                {
                    result.add(map_i);
                }
            }
        }
        return result;
    }


//    /**
//     *
//     * @param dataList
//     * @param key
//     * @return Predicate<T>
//     * @Author HLY
//     * @CreateTime 2022/11/24
//     * @Description: 根据key 去重
//     */
//    public static List<Map> dictinct(List<Map> dataList,String key){
//        List<Map> result = dataList.stream().filter(distinctByKey(o -> ((Map)o).get(key))).collect(Collectors.toList());
//        return result;
//    }

    /**
     * @param dataList
     * @param key
     * @return Predicate<T>
     * @Author HLY
     * @CreateTime 2022/11/24
     * @Description: 根据key 去重
     */
    public static MapList dictinct(MapList dataList, String key)
    {
        List<Map> list = (List<Map>) dataList.stream().filter(distinctByKey(o -> ((Map) o).get(key))).collect(Collectors.toList());
        MapList result = new MapList();
        result.addAll(list);
        return result;
    }


    /**
     * @param keyExtractor
     * @return Predicate<T>
     * @Author HLY
     * @CreateTime 2022/11/24
     * @Description: 根据key 去重
     */
    public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor)
    {
        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }


    /**
     * @param list1
     * @param list2
     * @param distinctKeyList
     * @param modAttrList
     * @return List<Map>
     * @Author HLY
     * @CreateTime 2022/11/24
     * @Description: 获取 两个集合中的差异数据 返回一个MapList  新的数据中的map 的 key  action 的值 有三种 add mod del
     * 代表 list2 中的数据 和 list1中的数据对比 新增的 修改的 去除的 三种情况
     */
    public static MapList getDifferenceData(MapList list1, MapList list2, StringList distinctKeyList, StringList modAttrList)
    {

        MapList result = new MapList();

        //把当前版本数据根据 differenceKey(差异判断主键)分组
        Map<String, List> currentCollect = (Map<String, List>) list1.stream().collect(Collectors.groupingBy(m ->
        {
            Map map = (Map) m;
            StringBuffer keyBuffer = new StringBuffer();
            for (int i = 0; i < distinctKeyList.size(); i++)
            {
                String key_i = distinctKeyList.get(i);
                String value_i = (String) map.get(key_i);
                if (UIUtil.isNullOrEmpty(value_i))
                {
                    value_i = "";
                }
                if (i < (distinctKeyList).size() - 1)
                {
                    keyBuffer.append(value_i);
                    keyBuffer.append("_");
                } else
                {
                    keyBuffer.append(value_i);
                }
            }
            return keyBuffer.toString();
        }));

        //把上一版本数据根据 differenceKey(差异判断主键)分组
        Map<String, List> previousCollect = (Map<String, List>) list2.stream().collect(Collectors.groupingBy(m ->
        {
            Map map = (Map) m;
            StringBuffer keyBuffer = new StringBuffer();
            for (int i = 0; i < distinctKeyList.size(); i++)
            {
                String key_i = distinctKeyList.get(i);
                String value_i = (String) map.get(key_i);
                if (UIUtil.isNullOrEmpty(value_i))
                {
                    value_i = "";
                }
                if (i < (distinctKeyList).size() - 1)
                {
                    keyBuffer.append(value_i);
                    keyBuffer.append("_");
                } else
                {
                    keyBuffer.append(value_i);
                }
            }
            return keyBuffer.toString();
        }));

        //当前版本的数据的  differenceKey(差异判断主键)集合
        Set<String> curentKeys = currentCollect.keySet();

        //上一版本的数据的  differenceKey(差异判断主键)集合
        Set<String> previousKeys = previousCollect.keySet();

        //创建一个临时的数据当前版本 differenceKey(差异判断主键)集合1
        Set tmpCurrentKeys1 = new HashSet<String>(curentKeys);

        //创建一个临时的数据上一版本 differenceKey(差异判断主键)集合1
        Set tmpPreviousKeys1 = new HashSet<String>(previousKeys);


        //创建一个临时的数据当前版本 differenceKey(差异判断主键)集合2
        Set tmpCurrentKeys2 = new HashSet<String>(curentKeys);

        //创建一个临时的数据上一版本 differenceKey(差异判断主键)集合2
        Set tmpPreviousKeys2 = new HashSet<String>(previousKeys);


        //创建一个临时的数据当前版本 differenceKey(差异判断主键)集合3
        Set tmpCurrentKeys3 = new HashSet<String>(curentKeys);

        //创建一个临时的数据上一版本 differenceKey(差异判断主键)集合3
        Set tmpPreviousKeys3 = new HashSet<String>(previousKeys);


        //获取新增数据 differenceKey(差异判断主键)集合
        tmpCurrentKeys1.removeAll(tmpPreviousKeys1);

        //获取取消数据 differenceKey(差异判断主键)集合
        tmpPreviousKeys2.removeAll(tmpCurrentKeys2);

        //获取交集
        tmpCurrentKeys3.retainAll(tmpPreviousKeys3);

        //添加增量数据
        Iterator<String> addIt = tmpCurrentKeys1.iterator();
        while (addIt.hasNext())
        {
            String addKey = addIt.next();
            List objects = currentCollect.get(addKey);
            objects.stream().forEach(m -> ((Map) m).put("action", "add"));
            result.addAll(objects);
        }


        //添加变更数据
        Iterator<String> retainIt_t = tmpCurrentKeys3.iterator();
        while (retainIt_t.hasNext())
        {
            String retainKey = retainIt_t.next();
            List currentObjs = currentCollect.get(retainKey);
            List previousObjs = previousCollect.get(retainKey);

            //正常情况只有一条数据
            if (currentObjs == null || currentObjs.size() == 0)
            {
                continue;
            }
            if (previousObjs == null || previousObjs.size() == 0)
            {
                continue;
            }

            Map map1 = (Map) currentObjs.get(0);
            Map map2 = (Map) previousObjs.get(0);

            boolean flag = checkModeData(map1, map2, modAttrList);
            if (!flag)
            {
                map1.put("action", "mod");
                result.add(map1);
            }
        }

        //添加废弃数据
        Iterator<String> cancelIt = tmpPreviousKeys2.iterator();
        while (cancelIt.hasNext())
        {
            String cancelKey = cancelIt.next();
            List objects = previousCollect.get(cancelKey);
            objects.stream().forEach(m -> ((Map) m).put("action", "del"));
            result.addAll(objects);
        }
        return result;
    }


    /**
     * 检查数据是否有变化
     *
     * @param map1
     * @param map2
     * @return
     */
    private static boolean checkModeData(Map map1, Map map2, StringList keys)
    {
//        Set keySet = map1.keySet();
//        Iterator iterator = keySet.iterator();
        boolean flag = true;

        for (int i = 0; i < keys.size(); i++)
        {
            String key_i = keys.get(i);
            String val1_i = (String) map1.get(key_i);
            String val2_i = (String) map2.get(key_i);

            if (UIUtil.isNullOrEmpty(val1_i) && UIUtil.isNullOrEmpty(val2_i))
            {
                continue;
            } else if (UIUtil.isNotNullAndNotEmpty(val1_i) && UIUtil.isNullOrEmpty(val2_i))
            {
                flag = false;
                break;
            } else if (UIUtil.isNullOrEmpty(val1_i) && UIUtil.isNotNullAndNotEmpty(val2_i))
            {
                flag = false;
                break;
            } else if (UIUtil.isNotNullAndNotEmpty(val1_i) && UIUtil.isNotNullAndNotEmpty(val2_i))
            {
                if (!val1_i.equals(val2_i))
                {
                    flag = false;
                    break;
                }
            }
        }

        return flag;
    }


    /**
     *
     * @param dataList
     * @param key
     * @return Map
     * @Author HLY
     * @CreateTime 2023/5/17
     * @Description: 根据 key 排序
     */
    public static Map groupingByKey(MapList dataList,String key){
        //把当前版本数据根据 key 分组
        Map<String, List<Map>> groupMap = (Map<String, List<Map>>) dataList.stream().collect(Collectors.groupingBy(m ->(String)((Map)m).get(key)));
        return groupMap;
    }

    public static void main(String[] args)
    {
//        List<Map> list = new ArrayList<Map>();
//        Map map0= new HashMap();
//        map0.put("id","000001");
//        map0.put("name","N000001");
//
//        Map map1= new HashMap();
//        map1.put("id","000001");
//        map1.put("name","N000002");
//
//        Map map2= new HashMap();
//        map2.put("id","000003");
//        map2.put("name","N000003");
//
//        MapList list = new MapList();
//
//        list.add(map0);
//        list.add(map1);
//        list.add(map2);
//
//        MapList nlist = dictinct(list, "id");
//        System.out.println("nlist : "+nlist);
//
//        MapList mapList = new MapList();

    }

}
